
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "dk-server/dk_core.h"
#include "data_server/ds_proto.h"
#include "data_server/util.h"


static DKEventThread *g_thread = NULL;

class UploadConn: public DKBaseConnection {
  virtual enum READ_STATUS OnRead() {
    TrackerHeader *header = (TrackerHeader *)evbuffer_pullup(get_input_buffer(), -1);
    fprintf(stderr, "ds resp: pkg_len:%d, cmd:%d, status:%d\n",
        Util::buff2long(header->pkg_len), header->cmd, header->status);
    evbuffer_drain(get_input_buffer(), -1);
    g_thread->Stop();
    return READ_ALL_DATA;
  }

  virtual void OnConnect() {
    fprintf(stderr, "new Connection fd:%d %s:%d\n", fd_, host_.c_str(), port_);
  }
  
  virtual void OnClose() {
    fprintf(stderr, "Connection close fd:%d %s:%d\n",
        fd_, host_.c_str(), port_); 
    g_thread->Stop();
  }

  virtual void OnError() {
    fprintf(stderr, "Connection Error %s\n", this->get_error_string());
    g_thread->Stop();
  }
};

static UploadConn *g_conn = NULL;
bool upload_file(const char *ds_host, int ds_port, const char *filename) {
  if (g_conn == NULL) {
    g_conn = new UploadConn(); 
    if (!g_conn) {
      fprintf(stderr, "new UploadConn fail\n");
      g_thread->Stop();
      return false;
    }

    if (!g_conn->Init(g_thread->get_base(), -1, ds_host, ds_port)) {
      fprintf(stderr, "UploadConn init fail\n");
      delete g_conn;
      g_conn = NULL;
      g_thread->Stop();
      return false;
    }
  }
  g_conn->set_timeout(10); 

  struct stat stat_buf;
  if (stat(filename, &stat_buf) != 0) {
    fprintf(stderr, "stat(\"%s\") fail:%s\n", filename, strerror(errno));
    g_thread->Stop();
    return false;
  }
 
  if (!S_ISREG(stat_buf.st_mode)) {
    fprintf(stderr, "not regular file:\"%s\"\n", filename);
    g_thread->Stop();
    return false;
  }

  int file_size = stat_buf.st_size;
  int fd = open(filename, O_RDONLY);

  TrackerHeader header;
  header.cmd = 0;
  header.status = 0;
  Util::long2buff(file_size, header.pkg_len);
  g_conn->Send(&header, sizeof(TrackerHeader));
  g_conn->SendFile(fd, 0, file_size);
  fprintf(stderr, "sendto %s:%d ...\n", ds_host, ds_port);
  return true;
}

int main(int argc, char **argv) {
  if (argc < 4) {
    fprintf(stderr, "Usage: ./ds_upload [ds_host] [ds_port] [filename]\n");
    return 0;
  }

  const char *ds_host = argv[1];
  int ds_port = atoi(argv[2]);
  const char *filename = argv[3];

  g_thread = new DKEventThread();
  if (g_thread == NULL)
    return 1;

  if (!g_thread->Init())
    return 1;

  bool ret = upload_file(ds_host, ds_port, filename);
  if (ret)
    g_thread->ThreadRoutine();

  delete g_thread;
  return !ret;
}
